Shader "Hidden/ColorDither"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Cull Off ZWrite Off ZTest Always

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o = (v2f)0;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex;
            uniform float4 _MainTex_TexelSize;
            uniform int _Iterate;

            uniform sampler2D _BlueNoiseTex;

            half _8x8DitherClip(half value, half2 sceneUVs)
            {
                if (value <= 0) return -0.1;
                half2 ditherUV = half2(fmod(sceneUVs.x, 8), fmod(sceneUVs.y, 8));
                const float dither[64] = {
                    0, 48, 12, 60,  3, 51, 15, 63,
                    32, 16, 44, 28, 35, 19, 47, 31,
                    8, 56,  4, 52, 11, 59,  7, 55,
                    40, 24, 36, 20, 43, 27, 39, 23,
                    2, 50, 14, 62,  1, 49, 13, 61,
                    34, 18, 46, 30, 33, 17, 45, 29,
                    10, 58,  6, 54, 9, 57,  5, 53,
                    42, 26, 38, 22, 41, 25, 37, 21 };
                int index = ditherUV.y * 8 + ditherUV.x;
                return value - dither[index] / 64;
            }

            inline fixed4 ExecuteDither(sampler2D tex, half2 duv, half2 uv, int iterate)
            {
                fixed4 dryCol = tex2D(tex, uv);

                fixed4 minValue = dryCol;
                fixed4 maxValue = dryCol;

                for (int x = -iterate; x <= iterate; x++)
                {
                    for (int y = -iterate; y <= iterate; y++)
                    {
                        fixed4 col = tex2D(tex, uv + duv * half2(x, y));
                        minValue = min(col, minValue);
                        maxValue = max(col, maxValue);
                    }
                }

                fixed4 delta = (maxValue - minValue);
                half2 ditherUv = uv*512;

                //8X8 Dither Version:
                //fixed4 wetCol = lerp(minValue, maxValue, step(0, _8x8DitherClip(delta.x, ditherUv)));

                //Blue Noise Version:
                fixed4 wetCol = lerp(minValue, maxValue, tex2D(_BlueNoiseTex, uv*5));
                return wetCol;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                return ExecuteDither(_MainTex, half2(_MainTex_TexelSize.x, _MainTex_TexelSize.y), i.uv, _Iterate);
            }
            ENDCG
        }
    }
}
